﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HPSocket;
using HPSocket.Tcp;

namespace HpSocketFunction
{
    /// <summary>
    /// Socket服务器类
    /// </summary>
    public class HpSocketServer
    {
        private readonly ITcpServer _server = new TcpServer();
        Dictionary<string, IntPtr> ClientItem = new Dictionary<string, IntPtr>();//设备状态字典

       // private bool IsHasStarted;

        /// <summary>
        /// 是否启动
        /// </summary>
        public bool IsHasStarted
        {
            get { return _server.HasStarted; }
       
        }


        /// <summary>
        /// 设备连接更新状态委托
        /// </summary>
        public delegate void ConnectItemStateDelegate(List<string> ClientItemMessage);
        /// <summary>
        /// 设备连接更新状态事件
        /// </summary>
        public event ConnectItemStateDelegate ConnectItemState;

        /// <summary>
        /// 接收数据委托
        /// </summary>
        /// <param name="ClientIp"></param>
        /// <param name="ClientPort"></param>
        /// <param name="data"></param>
        public delegate void OnReceiveMessageDelegate(string ClientIp, int ClientPort, byte[] data);
        /// <summary>
        /// 接收数据事件
        /// </summary>
        public event OnReceiveMessageDelegate OnReceiveMessage;

        /// <summary>
        /// 初始化Server
        /// </summary>
        /// <param name="ServeIp">服务器IP</param>
        /// <param name="Port">服务器端口</param>
        public HpSocketServer(string ServeIp, int Port)
        {
            // 缓冲区大小
            _server.SocketBufferSize = 4096;
            //ip
            _server.Address = ServeIp;
            //端口
            _server.Port = (ushort)Port;

            _server.OnPrepareListen += OnPrepareListen;//监听事件
            _server.OnAccept += OnAccept;//连接事件
            _server.OnReceive += OnReceive;//接收信息事件
            _server.OnClose += OnClose;//关闭事件
            _server.OnShutdown += OnShutdown;//关机事件
        }

        /// <summary>
        /// 监听响应
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="listen"></param>
        /// <returns></returns>
        private HandleResult OnPrepareListen(IServer sender, IntPtr listen)
        {
            string a = sender.Address;
            string b = sender.Port.ToString();
            string c = listen.ToString();
            string d = sender.Version;//版本

            return HandleResult.Ok;
        }


        /// <summary>
        /// 连接响应
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="connId"></param>
        /// <param name="client"></param>
        /// <returns></returns>
        private HandleResult OnAccept(IServer sender, IntPtr connId, IntPtr client)
        {
            string ip;
            ushort port;
            // 获取客户端地址
            if (!sender.GetRemoteAddress(connId, out  ip, out port))
            {
                return HandleResult.Error;
            }
            string ClientMessage = ip + ":" + port;
            if (!ClientItem.ContainsKey(ClientMessage))
            {
                ClientItem.Add(ClientMessage, connId);
            }
            string a = connId.ToString();
            string b = ip.ToString();
            string c = port.ToString();
            try
            {
                if (!(ConnectItemState==null))
                {
                    List<string> ClientRes = new List<string>(ClientItem.Keys);
                    ConnectItemState(ClientRes);
                }
                
            }
            catch (Exception)
            {
            }
            
            return HandleResult.Ok;
        }

      /// <summary>
      ///   接收数据响应
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="connId"></param>
      /// <param name="data"></param>
      /// <returns></returns>
        private HandleResult OnReceive(IServer sender, IntPtr connId, byte[] data)
        {
            string ip;
            ushort port;
            if (!sender.GetRemoteAddress(connId, out  ip, out  port))
            {
                return HandleResult.Error;
            }
            string ClientMessage = ip + ":" + port;
            if (!ClientItem.ContainsKey(ClientMessage))
            {
                ClientItem.Add(ClientMessage, connId);
            }
            
            string a = connId.ToString();
            string b = ip.ToString();
            string c = port.ToString();
            string d = Encoding.UTF8.GetString(data);
            try
            {
                if (!(OnReceiveMessage==null))
                {
                }
               
            }
            catch (Exception)
            {
            }
            return HandleResult.Ok;
                    OnReceiveMessage(ip, port, data);
        }

      /// <summary>
      /// 断开连接响应
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="connId"></param>
      /// <param name="socketOperation"></param>
      /// <param name="errorCode"></param>
      /// <returns></returns>
        private HandleResult OnClose(IServer sender, IntPtr connId, SocketOperation socketOperation, int errorCode)
        {
            string ip;
            ushort port;
            if (!sender.GetRemoteAddress(connId, out  ip, out  port))
            {
                return HandleResult.Error;
            }
            string a = connId.ToString();
            string b = socketOperation.ToString();
            string c = errorCode.ToString();
            string ClientMessage = ip + ":" + port;
            if (ClientItem.ContainsKey(ClientMessage))
            {
                ClientItem.Remove(ClientMessage);
            }
           
            try
            {
                if (!(ConnectItemState == null))
                {
                    List<string> ClientRes = new List<string>(ClientItem.Keys);
                    ConnectItemState(ClientRes);
                }
            }
            catch (Exception)
            {
            }
            return HandleResult.Ok;
        }

        /// <summary>
        /// 关机响应
        /// </summary>
        /// <param name="sender"></param>
        /// <returns></returns>
        private HandleResult OnShutdown(IServer sender)
        {
            string a = sender.Address;
            string b = sender.Port.ToString();


            return HandleResult.Ok;
        }

/// <summary>
/// 开启服务
/// </summary>
/// <returns></returns>
        public bool Start()
        {
            return _server.Start();
        }

        /// <summary>
        /// 关闭服务
        /// </summary>
        /// <returns></returns>
        public bool Close()
        {
            return _server.Stop();
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <returns></returns>
        public bool Dispose()
        {
            _server.Dispose();
            return true;
        } 

        /// <summary>
        ///是否连接正常状态
        /// </summary>
        /// <param name = "ClientIp" > 客户端IP </ param >
        /// < param name="ClientPort">客户端端口</param>
        /// <returns></returns>
        public bool IsConnected(string ClientIp, int ClientPort)
        {
            string ClientMessage = ClientIp + ":" + ClientPort;
            if (!ClientItem.ContainsKey(ClientMessage))
            {
                return false;
            }
            return _server.IsConnected(ClientItem[ClientMessage]);
        }


        /// <summary>
        /// 发送数据string
        /// </summary>
        /// <param name="ClientIp">客户端IP</param>
        /// <param name="ClientPort">客户端端口</param>
        /// <param name="Data">数据</param>
        /// <returns></returns>
        public bool SendData(string ClientIp, int ClientPort, string Data)
        {
            string ClientMessage = ClientIp + ":" + ClientPort;
            byte[] DataByte = Encoding.UTF8.GetBytes(Data);
            if (!ClientItem.ContainsKey(ClientMessage))
            {
                return false;
            }
            return _server.Send(ClientItem[ClientMessage], DataByte, DataByte.Length);
        }
    }
}
